package pile.customer.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import pile.customer.config.CustomerServiceWebSocketServerUtil;
import pile.customer.entity.Information;
import pile.customer.entity.ResponseResult;
import pile.customer.entity.User;
import pile.customer.params.ReceivingInformation;
import pile.customer.service.IInformationService;
import pile.customer.service.IUserService;
import pile.customer.service.IWeChatService;
import pile.customer.utils.HttpClientUtil;
import pile.customer.utils.WxUtil;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Service
@Log4j2
public class WeChatServiceImpl implements IWeChatService {


    @Autowired
    private IUserService userService;

    @Autowired
    private WxUtil wxUtil;

    @Autowired
    private IInformationService informationService;

    @Autowired
    private CustomerServiceWebSocketServerUtil customerServiceWebSocketServerUtil;
    /**
     * 请求接口验证
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @Override
    public String receiveGetRequest(String signature, String timestamp, String nonce, String echostr) {

        //1.将token、timestamp（URL参数中的）、nonce（URL参数中的）三个参数进行字典序排序，排序后结果为:["1714037059","486452656","AAAAA"]
        String[] params = {"7hTJn9KpW4qz5sGx3R6y2fDvE8c1bA5h", timestamp, nonce};
        // 对字符串数组进行字典序排序
        Arrays.sort(params);

        //2.将三个参数字符串拼接成一个字符串："1714037059486452656AAAAA"
        StringBuilder sb = new StringBuilder();
        for (String param : params) {
            sb.append(param);
        }
        String result = sb.toString();

        //3.进行sha1计算签名：899cf89e464efb63f54ddac96b0a0a235f53aa78
        String sha1 = sha1CalculateSignature(result);

        //4.与URL链接中的signature参数进行对比，相等说明请求来自微信服务器，合法。
        String resultData = "计算签名失败";
        if(sha1.equals(signature)){
            resultData = echostr;
        }

        return resultData;
    }

    /**
     * 接收消息
     */
    @Override
    public String acceptMessage(JSONObject data) {
        String[] params = {"7hTJn9KpW4qz5sGx3R6y2fDvE8c1bA5h",
                data.getStr("timestamp"),
                 data.getStr("nonce"),data.getStr("Encrypt")};
        Arrays.sort(params);
        // 对字符串数组进行字典序排序
        //2.将三个参数字符串拼接成一个字符串："1714037059486452656AAAAA"
        StringBuilder sb = new StringBuilder();
        for (String param : params) {
            sb.append(param);
        }
        String result = sb.toString();
        //3.进行sha1计算签名：899cf89e464efb63f54ddac96b0a0a235f53aa78
        String sha1 = sha1CalculateSignature(result);
        if(!data.getStr("msg_signature").equals(sha1)){
            return "签名验证失败";
        }
        String msg = decryptingCiphertextMethod(data.getStr("Encrypt"));
        if(msg == null){
            return "解密失败";
        }
        log.info("解密后的消息：{}",msg);

        //处理消息逻辑方法
        methodOfHandlingMessageLogic(msg);

        return "success";
    }

    /**
     * 发送给微信服务器
     * @param receivingInformation
     */
    @Override
    public ResponseResult sendMessage(ReceivingInformation receivingInformation) {

        //获取ACCESS_TOKEN
        String accessToken = wxUtil.getAccessToken(receivingInformation.getChannel());

        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+accessToken;
        Map params = new HashMap<>();
        params.put("touser", receivingInformation.getOpenId());
        //判断发送消息的类型
        if(receivingInformation.getMessageType() == 1){

            Map<String, String> text = new HashMap<>();
            text.put("content", receivingInformation.getMessage());
            params.put("msgtype", "text");
            params.put("text", text);
        }
        if(receivingInformation.getMessageType() == 2){
            Map image = new HashMap<>();
            image.put("media_id", receivingInformation.getMessage());
            params.put("msgtype", "image");
            params.put("image", image);
        }


        log.info("参数信息:"+JSONUtil.toJsonStr(params) );
        String result = HttpClientUtil.doPostJson(url, JSONUtil.toJsonStr(params));

        log.info("发送消息结果：{}",result);
        if(StringUtils.isEmpty(result)){
            log.error("发送消息到微信平台报错:"+result);
        }
        return new ResponseResult(JSONUtil.parseObj(result));
    }

    /**
     * 新增图片信息
     * @param uploadTempMedia
     * @param file
     * @return
     */
    @Override
    public ResponseResult uploadTempMedia(String uploadTempMedia, MultipartFile file)  {

        JSONObject data = JSONUtil.parseObj(uploadTempMedia);

        String accessToken = wxUtil.getAccessToken(data.getInt("channel"));

        Map<String, String> params = new HashMap<>();

        String url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token="+accessToken;

        params.put("type", data.getStr("type"));

        String result = HttpClientUtil.doPostWithFile(url, params,file);

        if(StringUtils.isEmpty(result)){
            return new ResponseResult("上传失败");
        }
        return new ResponseResult(JSONUtil.parseObj(result));
    }

    /**
     * 微信获取客服消息内的临时素材
     * @param mediaId
     * @param channel
     * @return
     */
    @Override
    public ResponseResult getTempMedia(String mediaId, Integer channel) throws IOException {

        String accessToken = wxUtil.getAccessToken(channel);

        String url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token="+accessToken+"&media_id="+mediaId;

        String result = HttpClientUtil.doGetBase64(url,null);
        if(StringUtils.isEmpty(result)){
            return new ResponseResult("获取失败");
        }

        return new ResponseResult(result);
    }

    /**
     * 处理消息逻辑方法
     * @param msg
     */
    private void methodOfHandlingMessageLogic(String msg) {

        JSONObject msgJson = JSONUtil.parseObj(msg);

        if(msgJson.getStr("MsgType").equals("event")){
            return;
        }


        //获取到openid
        String openid = msgJson.getStr("FromUserName");
        //根据openid查询用户信息是否存在
        User user = userService.selectByOpenId(openid);

        //消息存数据库
        Information information = new Information();


        information.setOpenId(openid);
        //类型
        information.setType(1);
        //消息类型
        if(msgJson.getStr("MsgType").equals("text")){
            information.setMessageType(1);
        }
        if(msgJson.getStr("MsgType").equals("image")){
            information.setMessageType(2);
        }


        //判断用户是否存在方法
        determineWhetherTheUserHasAMethod(msgJson,user);
        information.setMessage(user.getLastMessage());
        informationService.add(information);
        try {
            //找到在线客服 给客服发送消息
            ReceivingInformation receivingInformation = new ReceivingInformation();

            //消息
            receivingInformation.setMessage(user.getLastMessage());
            //openid
            receivingInformation.setOpenId(user.getOpenId());
            //发送时间
            receivingInformation.setSendingTime(new Date());
            //客服账号
            String targetAccount = user.getCustomerServiceAccount();

            //消息类型
            receivingInformation.setMessageType(information.getMessageType());
            //渠道
            receivingInformation.setChannel(user.getChannel());
            // 使用三元表达式简化条件判断和消息发送逻辑
            customerServiceWebSocketServerUtil.sendInfo(JSONUtil.toJsonStr(receivingInformation), targetAccount == null ? null : targetAccount);
            log.info("发送给客服消息成功:" + JSONUtil.toJsonStr(receivingInformation));
        } catch (Exception e) {
            log.error("用户发送给客服消息报错:" + e);
        }


    }

    /**
     * 判断用户是否存在
     * @param msgJson
     * @param user
     */
    private void determineWhetherTheUserHasAMethod(JSONObject msgJson, User user) {

        //获取到openid
        String openid = msgJson.getStr("FromUserName");
        //获取小程序标识
        String toUserName = msgJson.getStr("ToUserName");

        String content = null;

        Integer messageType = 1;
        if(msgJson.getStr("MsgType").equals("image")){
            content = msgJson.getStr("MediaId");
            messageType = 2;
        }

        if(msgJson.getStr("MsgType").equals("text")){
            content = msgJson.getStr("Content");
        }

        Integer channel = 1;
        if(toUserName.equals("gh_a5af160ee14d")){
            //代表是阿凡电小程序
            channel = 3;
        }
        if (user != null) {
            //修改为在线
            user.setIsOnLine(1);
            //发送消息
            user.setLastMessage(content);
            //发送者类型
            user.setLastMessageType(1);
            //最后一次发送时间
            user.setLastMessageTime(new Date());
            //未接入数量
            user.setNoAccessNum(1);
            user.setChannel(channel);
            //信息类型
            user.setMessageType(messageType);

            if (user.getIsDisplay() == 2) {
                //不显示 要添加未接入数量
                user.setNoAccessNum(user.getNoAccessNum() + 1);
                //未读消息数量
                user.setUnreadQuantity(user.getUnreadQuantity() + 1);
            }else{
                //未读消息数量+1
                user.setUnreadQuantity(user.getUnreadQuantity() + 1);
                //是否回复修改未回复
                user.setIsReply(1);
            }

            userService.updateById(user);
            return;
        }
        //不存在添加  新用户肯定没有发送过消息
        User userAdd = new User();

        //发送消息
        userAdd.setLastMessage(content);
        //未接入数量
        userAdd.setNoAccessNum(1);
        //发送者类型
        userAdd.setLastMessageType(1);
        //最后一次发送时间
        userAdd.setLastMessageTime(new Date());
        //opneid
        userAdd.setOpenId(openid);
        //渠道
        userAdd.setChannel(1);
        //在线
        userAdd.setIsOnLine(1);
        //不显示
        userAdd.setIsDisplay(2);
        //小程序渠道
        userAdd.setChannel(channel);
        userService.add(userAdd);

    }

    /**
     * 验签方法
     * @param result
     * @return
     */
    private String sha1CalculateSignature(String result){

        String sha1Hash = "";
        try {
            // 创建MessageDigest对象并指定算法为SHA-1
            MessageDigest digest = MessageDigest.getInstance("SHA-1");

            // 将输入字符串转换为字节数组
            byte[] inputBytes = result.getBytes();

            // 更新MessageDigest对象的摘要信息
            digest.update(inputBytes);

            // 计算摘要信息
            byte[] hashBytes = digest.digest();

            // 将字节数组转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
             sha1Hash = sb.toString();

            // 打印SHA-1签名结果
           return sha1Hash;

        } catch (NoSuchAlgorithmException e) {
            System.err.println("SHA-1算法不可用：" + e.getMessage());
        }
        return sha1Hash;
    }

    /**
     * 解密密文方法
     * @param encrypt
     * @return
     */
    private  String decryptingCiphertextMethod(String encrypt) {

        try{
            String encodingAESKey = "jxm9EhQaec0FOxtIEfhv4mgg0ddhATeErfxebVbtLWe";
            // 填充"="字符
            String paddedKey = encodingAESKey + "=";
            // 使用Base64解码
            byte[] decodedKey = Base64.getDecoder().decode(paddedKey);

            // 生成32字节的AESKey
            byte[] aesKey = new byte[32];
            System.arraycopy(decodedKey, 0, aesKey, 0, 32);


            // 使用BASE64对密文进行解码
            byte[] encrypted = Base64.getDecoder().decode(encrypt);

            byte[] decodedBytes = new byte[0];

            // 使用AES密钥对密文进行解密
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
            cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);


            // 解密
            decodedBytes = cipher.doFinal(encrypted);
            // 提取消息长度部分
            byte[] msgLenBytes = new byte[4];
            System.arraycopy(decodedBytes, 16, msgLenBytes, 0, 4);
            int msgLength = ByteBuffer.wrap(msgLenBytes).getInt();

            // 提取消息内容部分
            byte[] msgBytes = new byte[msgLength];
            System.arraycopy(decodedBytes, 20, msgBytes, 0, msgLength);
            String msg = new String(msgBytes);

            return msg;
        }catch (Exception e){
            log.error("解密密文报错:"+e);
        }

        return null;
    }


}
